home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / jpsrc2.zip / JRDTARGA.C < prev    next >
C/C++ Source or Header  |  1991-12-12  |  14KB  |  484 lines

  1. /*
  2.  * jrdtarga.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to read input images in Targa format.
  9.  *
  10.  * These routines may need modification for non-Unix environments or
  11.  * specialized applications.  As they stand, they assume input from
  12.  * an ordinary stdio stream.  They further assume that reading begins
  13.  * at the start of the file; input_init may need work if the
  14.  * user interface has already read some data (e.g., to determine that
  15.  * the file is indeed Targa format).
  16.  *
  17.  * These routines are invoked via the methods get_input_row
  18.  * and input_init/term.
  19.  *
  20.  * Based on code contributed by Lee Daniel Crocker.
  21.  */
  22.  
  23. #include "jinclude.h"
  24.  
  25. #ifdef TARGA_SUPPORTED
  26.  
  27.  
  28. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  29.  
  30. #ifdef HAVE_UNSIGNED_CHAR
  31. typedef unsigned char U_CHAR;
  32. #define UCH(x)    ((int) (x))
  33. #else /* !HAVE_UNSIGNED_CHAR */
  34. #ifdef CHAR_IS_UNSIGNED
  35. typedef char U_CHAR;
  36. #define UCH(x)    ((int) (x))
  37. #else
  38. typedef char U_CHAR;
  39. #define UCH(x)    ((int) (x) & 0xFF)
  40. #endif
  41. #endif /* HAVE_UNSIGNED_CHAR */
  42.  
  43.  
  44. #define    ReadOK(file,buffer,len)    (FREAD(file,buffer,len) == ((size_t) (len)))
  45.  
  46.  
  47. static JSAMPARRAY colormap;    /* Targa colormap (converted to my format) */
  48.  
  49. static big_sarray_ptr whole_image; /* Needed if funny input row order */
  50. static long current_row;    /* Current logical row number to read */
  51.  
  52. /* Pointer to routine to extract next Targa pixel from input file */
  53. static void (*read_pixel) PP((compress_info_ptr cinfo));
  54.  
  55. /* Result of read_pixel is delivered here: */
  56. static U_CHAR tga_pixel[4];
  57.  
  58. static int pixel_size;        /* Bytes per Targa pixel (1 to 4) */
  59.  
  60. /* State info for reading RLE-coded pixels; both counts must be init to 0 */
  61. static int block_count;        /* # of pixels remaining in RLE block */
  62. static int dup_pixel_count;    /* # of times to duplicate previous pixel */
  63.  
  64. /* This saves the correct pixel-row-expansion method for preload_image */
  65. static void (*get_pixel_row) PP((compress_info_ptr cinfo,
  66.                  JSAMPARRAY pixel_row));
  67.  
  68.  
  69. /* For expanding 5-bit pixel values to 8-bit with best rounding */
  70.  
  71. static const UINT8 c5to8bits[32] = {
  72.     0,   8,  16,  24,  32,  41,  49,  57,
  73.    65,  74,  82,  90,  98, 106, 115, 123,
  74.   131, 139, 148, 156, 164, 172, 180, 189,
  75.   197, 205, 213, 222, 230, 238, 246, 255
  76. };
  77.  
  78.  
  79.  
  80. LOCAL int
  81. read_byte (compress_info_ptr cinfo)
  82. /* Read next byte from Targa file */
  83. {
  84.   register FILE *infile = cinfo->input_file;
  85.   register int c;
  86.  
  87.   if ((c = getc(infile)) == EOF)
  88.     ERREXIT(cinfo->emethods, "Premature EOF in Targa file");
  89.   return c;
  90. }
  91.  
  92.  
  93. LOCAL void
  94. read_colormap (compress_info_ptr cinfo, int cmaplen, int mapentrysize)
  95. /* Read the colormap from a Targa file */
  96. {
  97.   int i;
  98.  
  99.   /* Presently only handles 24-bit BGR format */
  100.   if (mapentrysize != 24)
  101.     ERREXIT(cinfo->emethods, "Unsupported Targa colormap format");
  102.  
  103.   for (i = 0; i < cmaplen; i++) {
  104.     colormap[2][i] = (JSAMPLE) read_byte(cinfo);
  105.     colormap[1][i] = (JSAMPLE) read_byte(cinfo);
  106.     colormap[0][i] = (JSAMPLE) read_byte(cinfo);
  107.   }
  108. }
  109.  
  110.  
  111. /*
  112.  * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
  113.  */
  114.  
  115. LOCAL void
  116. read_non_rle_pixel (compress_info_ptr cinfo)
  117. /* Read one Targa pixel from the input file; no RLE expansion */
  118. {
  119.   register FILE * infile = cinfo->input_file;
  120.   register int i;
  121.  
  122.   for (i = 0; i < pixel_size; i++) {
  123.     tga_pixel[i] = (U_CHAR) getc(infile);
  124.   }
  125. }
  126.  
  127.  
  128. LOCAL void
  129. read_rle_pixel (compress_info_ptr cinfo)
  130. /* Read one Targa pixel from the input file, expanding RLE data as needed */
  131. {
  132.   register FILE * infile = cinfo->input_file;
  133.   register int i;
  134.  
  135.   /* Duplicate previously read pixel? */
  136.   if (dup_pixel_count > 0) {
  137.     dup_pixel_count--;
  138.     return;
  139.   }
  140.  
  141.   /* Time to read RLE block header? */
  142.   if (--block_count < 0) {    /* decrement pixels remaining in block */
  143.     i = read_byte(cinfo);
  144.     if (i & 0x80) {        /* Start of duplicate-pixel block? */
  145.       dup_pixel_count = i & 0x7F; /* number of duplications after this one */
  146.       block_count = 0;        /* then read new block header */
  147.     } else {
  148.       block_count = i & 0x7F;    /* number of pixels after this one */
  149.     }
  150.   }
  151.  
  152.   /* Read next pixel */
  153.   for (i = 0; i < pixel_size; i++) {
  154.     tga_pixel[i] = (U_CHAR) getc(infile);
  155.   }
  156. }
  157.  
  158.  
  159. /*
  160.  * Read one row of pixels.
  161.  *
  162.  * We provide several different versions depending on input file format.
  163.  */
  164.  
  165.  
  166. METHODDEF void
  167. get_8bit_gray_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  168. /* This version is for reading 8-bit grayscale pixels */
  169. {
  170.   register JSAMPROW ptr0;
  171.   register long col;
  172.   
  173.   ptr0 = pixel_row[0];
  174.   for (col = cinfo->image_width; col > 0; col--) {
  175.     (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  176.     *ptr0++ = (JSAMPLE) UCH(tga_pixel[0]);
  177.   }
  178. }
  179.  
  180. METHODDEF void
  181. get_8bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  182. /* This version is for reading 8-bit colormap indexes */
  183. {
  184.   register int t;
  185.   register JSAMPROW ptr0, ptr1, ptr2;
  186.   register long col;
  187.   
  188.   ptr0 = pixel_row[0];
  189.   ptr1 = pixel_row[1];
  190.   ptr2 = pixel_row[2];
  191.   for (col = cinfo->image_width; col > 0; col--) {
  192.     (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  193.     t = UCH(tga_pixel[0]);
  194.     *ptr0++ = colormap[0][t];
  195.     *ptr1++ = colormap[1][t];
  196.     *ptr2++ = colormap[2][t];
  197.   }
  198. }
  199.  
  200. METHODDEF void
  201. get_16bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  202. /* This version is for reading 16-bit pixels */
  203. {
  204.   register int t;
  205.   register JSAMPROW ptr0, ptr1, ptr2;
  206.   register long col;
  207.   
  208.   ptr0 = pixel_row[0];
  209.   ptr1 = pixel_row[1];
  210.   ptr2 = pixel_row[2];
  211.   for (col = cinfo->image_width; col > 0; col--) {
  212.     (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  213.     t = UCH(tga_pixel[0]);
  214.     t += UCH(tga_pixel[1]) << 8;
  215.     /* We expand 5 bit data to 8 bit sample width.
  216.      * The format of the 16-bit (LSB first) input word is
  217.      *     xRRRRRGGGGGBBBBB
  218.      */
  219.     *ptr2++ = (JSAMPLE) c5to8bits[t & 0x1F];
  220.     t >>= 5;
  221.     *ptr1++ = (JSAMPLE) c5to8bits[t & 0x1F];
  222.     t >>= 5;
  223.     *ptr0++ = (JSAMPLE) c5to8bits[t & 0x1F];
  224.   }
  225. }
  226.  
  227. METHODDEF void
  228. get_24bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  229. /* This version is for reading 24-bit pixels */
  230. {
  231.   register JSAMPROW ptr0, ptr1, ptr2;
  232.   register long col;
  233.   
  234.   ptr0 = pixel_row[0];
  235.   ptr1 = pixel_row[1];
  236.   ptr2 = pixel_row[2];
  237.   for (col = cinfo->image_width; col > 0; col--) {
  238.     (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  239.     *ptr0++ = (JSAMPLE) UCH(tga_pixel[2]); /* convert BGR to RGB order */
  240.     *ptr1++ = (JSAMPLE) UCH(tga_pixel[1]);
  241.     *ptr2++ = (JSAMPLE) UCH(tga_pixel[0]);
  242.   }
  243. }
  244.  
  245. METHODDEF void
  246. get_32bit_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  247. /* This version is for reading 32-bit pixels */
  248. /* Attribute bits are ignored for now */
  249. {
  250.   register JSAMPROW ptr0, ptr1, ptr2;
  251.   register long col;
  252.  
  253. /* NOTE: there seems to be considerable confusion over whether the order
  254.  * of the bytes in a 32-bit Targa file is A,B,G,R or B,G,R,A.
  255.  * On Lee Crocker's authority, we think the attribute byte comes first.
  256.  * Make ATTR_BYTE_FIRST be 0 if you have files in which it comes last.
  257.  */
  258. #ifndef ATTR_BYTE_FIRST    /* so you can say -DATTR_BYTE_FIRST=0 in Makefile */
  259. #define ATTR_BYTE_FIRST  1    /* must be 0 or 1 */
  260. #endif
  261.   
  262.   ptr0 = pixel_row[0];
  263.   ptr1 = pixel_row[1];
  264.   ptr2 = pixel_row[2];
  265.   for (col = cinfo->image_width; col > 0; col--) {
  266.     (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  267.     /* convert ABGR (or BGRA) to RGB order */
  268.     *ptr0++ = (JSAMPLE) UCH(tga_pixel[2+ATTR_BYTE_FIRST]);
  269.     *ptr1++ = (JSAMPLE) UCH(tga_pixel[1+ATTR_BYTE_FIRST]);
  270.     *ptr2++ = (JSAMPLE) UCH(tga_pixel[0+ATTR_BYTE_FIRST]);
  271.   }
  272. }
  273.  
  274.  
  275. /*
  276.  * This method is for re-reading the input data in standard top-down
  277.  * row order.  The entire image has already been read into whole_image
  278.  * with proper conversion of pixel format, but it's in a funny row order.
  279.  */
  280.  
  281. METHODDEF void
  282. get_memory_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  283. {
  284.   JSAMPARRAY image_ptr;
  285.   long source_row;
  286.  
  287.   /* Compute row of source that maps to current_row of normal order */
  288.   /* For now, assume image is bottom-up and not interlaced. */
  289.   /* NEEDS WORK to support interlaced images! */
  290.   source_row = cinfo->image_height - current_row - 1;
  291.  
  292.   /* Fetch that row from virtual array */
  293.   image_ptr = (*cinfo->emethods->access_big_sarray)
  294.         (whole_image, source_row * cinfo->input_components, FALSE);
  295.  
  296.   jcopy_sample_rows(image_ptr, 0, pixel_row, 0,
  297.             cinfo->input_components, cinfo->image_width);
  298.  
  299.   current_row++;
  300. }
  301.  
  302.  
  303. /*
  304.  * This method loads the image into whole_image during the first call on
  305.  * get_input_row.  The get_input_row pointer is then adjusted to call
  306.  * get_memory_row on subsequent calls.
  307.  */
  308.  
  309. METHODDEF void
  310. preload_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  311. {
  312.   JSAMPARRAY image_ptr;
  313.   long row;
  314.  
  315.   /* Read the data into a virtual array in input-file row order */
  316.   for (row = 0; row < cinfo->image_height; row++) {
  317.     image_ptr = (*cinfo->emethods->access_big_sarray)
  318.             (whole_image, row * cinfo->input_components, TRUE);
  319.     (*get_pixel_row) (cinfo, image_ptr);
  320.   }
  321.   /* Set up to read from the virtual array in unscrambled order */
  322.   cinfo->methods->get_input_row = get_memory_row;
  323.   current_row = 0;
  324.   /* And read the first row */
  325.   get_memory_row(cinfo, pixel_row);
  326. }
  327.  
  328.  
  329. /*
  330.  * Read the file header; return image size and component count.
  331.  */
  332.  
  333. METHODDEF void
  334. input_init (compress_info_ptr cinfo)
  335. {
  336.   U_CHAR targaheader[18];
  337.   int idlen, cmaptype, subtype, flags, interlace_type, components;
  338.   UINT16 width, height, maplen;
  339.   boolean is_bottom_up;
  340.  
  341. #define GET_2B(offset)    ((unsigned int) UCH(targaheader[offset]) + \
  342.              (((unsigned int) UCH(targaheader[offset+1])) << 8))
  343.   
  344.   if (! ReadOK(cinfo->input_file, targaheader, 18))
  345.     ERREXIT(cinfo->emethods, "Unexpected end of file");
  346.  
  347.   /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  348.   if (targaheader[16] == 15)
  349.     targaheader[16] = 16;
  350.  
  351.   idlen = UCH(targaheader[0]);
  352.   cmaptype = UCH(targaheader[1]);
  353.   subtype = UCH(targaheader[2]);
  354.   maplen = GET_2B(5);
  355.   width = GET_2B(12);
  356.   height = GET_2B(14);
  357.   pixel_size = UCH(targaheader[16]) >> 3;
  358.   flags = UCH(targaheader[17]);    /* Image Descriptor byte */
  359.  
  360.   is_bottom_up = ((flags & 0x20) == 0);    /* bit 5 set => top-down */
  361.   interlace_type = flags >> 6;    /* bits 6/7 are interlace code */
  362.  
  363.   if (cmaptype > 1 ||        /* cmaptype must be 0 or 1 */
  364.       pixel_size < 1 || pixel_size > 4 ||
  365.       (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
  366.       interlace_type != 0)    /* currently don't allow interlaced image */
  367.     ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  368.   
  369.   if (subtype > 8) {
  370.     /* It's an RLE-coded file */
  371.     read_pixel = read_rle_pixel;
  372.     block_count = dup_pixel_count = 0;
  373.     subtype -= 8;
  374.   } else {
  375.     /* Non-RLE file */
  376.     read_pixel = read_non_rle_pixel;
  377.   }
  378.  
  379.   /* Now should have subtype 1, 2, or 3 */
  380.   components = 3;        /* until proven different */
  381.   cinfo->in_color_space = CS_RGB;
  382.  
  383.   switch (subtype) {
  384.   case 1:            /* colormapped image */
  385.     if (pixel_size == 1 && cmaptype == 1)
  386.       get_pixel_row = get_8bit_row;
  387.     else
  388.       ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  389.     break;
  390.   case 2:            /* RGB image */
  391.     switch (pixel_size) {
  392.     case 2:
  393.       get_pixel_row = get_16bit_row;
  394.       break;
  395.     case 3:
  396.       get_pixel_row = get_24bit_row;
  397.       break;
  398.     case 4:
  399.       get_pixel_row = get_32bit_row;
  400.       break;
  401.     default:
  402.       ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  403.       break;
  404.     }
  405.     break;
  406.   case 3:            /* Grayscale image */
  407.     components = 1;
  408.     cinfo->in_color_space = CS_GRAYSCALE;
  409.     if (pixel_size == 1)
  410.       get_pixel_row = get_8bit_gray_row;
  411.     else
  412.       ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  413.     break;
  414.   default:
  415.     ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  416.     break;
  417.   }
  418.  
  419.   if (is_bottom_up) {
  420.     whole_image = (*cinfo->emethods->request_big_sarray)
  421.             ((long) width, (long) height * components,
  422.              (long) components);
  423.     cinfo->methods->get_input_row = preload_image;
  424.   } else {
  425.     whole_image = NULL;
  426.     cinfo->methods->get_input_row = get_pixel_row;
  427.   }
  428.   
  429.   while (idlen--)        /* Throw away ID field */
  430.     (void) read_byte(cinfo);
  431.  
  432.   if (maplen > 0) {
  433.     if (maplen > 256 || GET_2B(3) != 0)
  434.       ERREXIT(cinfo->emethods, "Colormap too large");
  435.     /* Allocate space to store the colormap */
  436.     colormap = (*cinfo->emethods->alloc_small_sarray)
  437.             ((long) maplen, 3L);
  438.     /* and read it from the file */
  439.     read_colormap(cinfo, (int) maplen, UCH(targaheader[7]));
  440.   } else {
  441.     if (cmaptype)        /* but you promised a cmap! */
  442.       ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  443.     colormap = NULL;
  444.   }
  445.  
  446.   cinfo->input_components = components;
  447.   cinfo->image_width = width;
  448.   cinfo->image_height = height;
  449.   cinfo->data_precision = 8;    /* always, even if 12-bit JSAMPLEs */
  450. }
  451.  
  452.  
  453. /*
  454.  * Finish up at the end of the file.
  455.  */
  456.  
  457. METHODDEF void
  458. input_term (compress_info_ptr cinfo)
  459. {
  460.   if (whole_image != NULL)
  461.     (*cinfo->emethods->free_big_sarray) (whole_image);
  462.   if (colormap != NULL)
  463.     (*cinfo->emethods->free_small_sarray) (colormap, 3L);
  464. }
  465.  
  466.  
  467. /*
  468.  * The method selection routine for Targa format input.
  469.  * Note that this must be called by the user interface before calling
  470.  * jpeg_compress.  If multiple input formats are supported, the
  471.  * user interface is responsible for discovering the file format and
  472.  * calling the appropriate method selection routine.
  473.  */
  474.  
  475. GLOBAL void
  476. jselrtarga (compress_info_ptr cinfo)
  477. {
  478.   cinfo->methods->input_init = input_init;
  479.   /* cinfo->methods->get_input_row is set by input_init */
  480.   cinfo->methods->input_term = input_term;
  481. }
  482.  
  483. #endif /* TARGA_SUPPORTED */
  484.